﻿using DevExpress.ExpressApp.Security;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security.Claims;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Security.Claims;
using YAKEJI.Abp.Domain.Repositories;
using YAPACS.Organizations;

namespace YAPACS.RisServer.Pages.Account;

public partial class LoginModel : AbpPageModel
{
    [Required(ErrorMessage = "用户名不能为空")]
    [BindProperty]
    [DisplayName("用户名")]
    public string UserName { get; set; }

    [BindProperty]
    [DisplayName("密码")]
    public string Password { get; set; }

    [Required(ErrorMessage = "请选择用户组")]
    [BindProperty]
    [DisplayName("用户组")]
    public string UserGroup { get; set; }

    [BindProperty]
    [DisplayName("记住我")]
    public bool RememberMe { get; set; }

    private readonly IRepository<ApplicationUser, Guid> _userRepository;
    private readonly IRepository<UserLoginLog, Guid> _userLoginLogRepository;
    private readonly SignInManager _signInManager;

    public LoginModel(
        IRepository<UserLoginLog, Guid> userLoginLogRepository,
        IRepository<ApplicationUser, Guid> userRepository,
        SignInManager signInManager)
    {
        _userLoginLogRepository = userLoginLogRepository;
        _userRepository = userRepository;
        _signInManager = signInManager;
    }

    private async Task AddLoginLogAsync(ApplicationUser user, string groupName)
    {
        var userLoginLog = await _userLoginLogRepository.NewEntityAsync();
        userLoginLog.UserId = user.Id;
        userLoginLog.UserName = user.UserName;
        userLoginLog.Name = user.Name;
        userLoginLog.GroupName = groupName;
        userLoginLog.StationCode = Request.Cookies["StationCode"];
        userLoginLog.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();
        userLoginLog.UserAgent = Request.Headers.UserAgent;
        userLoginLog.LoginTime = Clock.Now;
    }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            var logonParams = new OrganizationLogonParameters(UserName, Password);
            var authResult = _signInManager.AuthenticateByLogonParameters(logonParams);
            if (authResult.Succeeded)
            {
                var claims = authResult.Principal.Claims.ToList();
                var userId = authResult.Principal.FindFirstValue(ClaimTypes.NameIdentifier);

                var user = await _userRepository.FindAsync(Guid.Parse(userId));
                if (user.IsActive)
                {
                    if (!string.IsNullOrWhiteSpace(user.Name))
                    {
                        claims.Add(new Claim(AbpClaimTypes.Name, user.Name));
                    }

                    if (!string.IsNullOrWhiteSpace(user.JobNumber))
                    {
                        claims.Add(new Claim("job-number", user.JobNumber));
                    }

                    var args = UserGroup.Split('@');
                    if (args.Length > 2)
                    {
                        claims.Add(new Claim("user-group-id", args[0]));
                        claims.Add(new Claim("department-id", args[1]));
                        claims.Add(new Claim("institution-id", args[2]));
                    }

                    var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));

                    var authProperties = new AuthenticationProperties
                    {
                        IsPersistent = RememberMe,
                        ExpiresUtc = DateTime.UtcNow.AddMonths(1)
                    };

                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, authProperties);
                    await AddLoginLogAsync(user, args.Length > 3 ? args[3] : null);

                    return LocalRedirect(returnUrl ?? Url.Content("~/"));
                }
                else
                {
                    ModelState.AddModelError("", "用户已被禁用");
                }
            }
            else
            {
                ModelState.AddModelError("", "用户名或密码不正确");
            }
        }

        return Page();
    }
}
